let gameState = 'warning'
let gameStartAnimationTime = undefined
let gameWinAnimationTime = undefined
let gameCreditAnimationTime = undefined
let gameCurrentNight = 0
let gameStar = 0
let gameNextAction = undefined
let config = undefined
let state = undefined
let iota = {}
let omicron = {}
let alpha = {}
let omega = {}

// Manage storage
function saveToStorage() {
	localStorage.setItem(GAME_CONFIG.storageKey, JSON.stringify({
		cur: gameCurrentNight,
		star: gameStar
	}))
}

let storage = JSON.parse(localStorage.getItem(GAME_CONFIG.storageKey))
if (storage) {
	gameCurrentNight = storage.cur
	gameStar = storage.star
} else saveToStorage()

// Game win
function gameWin() {
	gameState = 'win'
	gameWinAnimationTime = 0
	if (config.star)
		gameStar |= config.star
	if (gameCurrentNight + 1 < GAME_CONFIG.levels.length) {
		gameNextAction = 'nextlevel'
		config = GAME_CONFIG.levels[++gameCurrentNight]
	} else {
		gameNextAction = 'ending'
	}
	saveToStorage()

	stopAllAudio()
	playAudio('assets/sound/win.mp3')
}

// Get glitch image
function getGlitchImage(name) {
	let randomNumber = Math.floor(Math.random() * 100)
	return 'assets/character/' + ((randomNumber < 4) ? ('glitch/' + name + randomNumber.toString()) : name) + '.png'
}

// Update frame
function update(elapsed) {
	switch (gameState) {
		case 'warning':
		case 'warning1':
			// Draw background
			fillRect(0, 0, 800, 600, { fill: '#222' })

			// Draw game title text
			fillText('WARNING', 400, 200, { fontSize: 72 })
			fillText('This game contains', 400, 300, { fontSize: 36 })
			fillText('flashing lights, loud noises', 400, 350, { fontSize: 36 })
			fillText('and jumpscares!', 400, 400, { fontSize: 36 })
			if (gameState == 'warning1')
				fillText('(Release mouse to continue)', 400, 450)
			else
				fillText('(Click anywhere to continue)', 400, 450)
			if (MOUSE_STATE.click)
				gameState = 'warning1'
			else if (gameState == 'warning1') {
				gameState = 'start'
				playAudio('assets/sound/music.ogg', true)
			}
			break
		case 'start':
			// Draw background
			fillRect(0, 0, 800, 600, { fill: '#222' })

			// Draw game title text
			fillText('FIVE', 200, 100, { fontSize: 72 })
			fillText('NIGHT', 200, 175, { fontSize: 72 })
			fillText('AT', 200, 250, { fontSize: 72 })
			fillText('IOTA\'S', 200, 325, { fontSize: 72 })

			// Draw star
			if (gameStar & 1)
				fillText('★', 150, 375, { fontSize: 48 })
			if (gameStar & 2)
				fillText('★', 200, 375, { fontSize: 48 })
			if (gameStar & 4)
				fillText('★', 250, 375, { fontSize: 48 })

			// Draw start game button
			let startGameButton = uiRectButton(80, 400, 240, 50, { fillHover: '#444', fillClick: '#666' })
			fillText('START', 200, 427, { fontSize: 30 })
			fillText(GAME_CONFIG.levels[gameCurrentNight].name, 360, 435, { fontSize: 15 })

			// Draw extra level button
			let extraLevelButton = false
			if (gameStar & 1) {
				extraLevelButton = uiRectButton(80, 460, 240, 50, { fillHover: '#444', fillClick: '#666' })
				fillText(GAME_CONFIG.extraLevel.name, 200, 487, { fontSize: 30 })
			}

			// Draw custom level button
			let customLevelButton = false
			if (gameStar & 2) {
				customLevelButton = uiRectButton(80, 520, 240, 50, { fillHover: '#444', fillClick: '#666' })
				fillText('CUSTOM NIGHT', 200, 547, { fontSize: 30 })
			}

			// Draw characters
			drawImage(getGlitchImage('omega'), 225, 0, 500, 500)
			drawImage(getGlitchImage('alpha'), 300, 50, 500, 500)
			drawImage(getGlitchImage('omicron'), 375, 100, 500, 500)
			drawImage(getGlitchImage('iota'), 450, 150, 500, 500)

			// Draw glitch
			drawGlitch(0, 0, 800, 600)

			// Handle start game button events
			if (startGameButton) {
				config = GAME_CONFIG.levels[gameCurrentNight]
				gameState = 'gameStartAnimation'
				gameStartAnimationTime = 0
				stopAllAudio()
			} else if (extraLevelButton) {
				config = GAME_CONFIG.extraLevel
				gameState = 'gameStartAnimation'
				gameStartAnimationTime = 0
				stopAllAudio()
			} else if (customLevelButton) {
				gameState = 'customLevel'
			}
			break
		case 'customLevel':
			// Draw background
			fillRect(0, 0, 800, 600, { fill: '#222' })

			// Draw iota selector
			drawImage('assets/character/iota.png', 0, 50, 200, 200)
			uiIntegerSelector(iota, 0, 250, { fillHover: '#444', fillClick: '#666' })

			// Draw omicron selector
			drawImage('assets/character/omicron.png', 200, 50, 200, 200)
			uiIntegerSelector(omicron, 200, 250, { fillHover: '#444', fillClick: '#666' })

			// Draw alpha selector
			drawImage('assets/character/alpha.png', 400, 50, 200, 200)
			uiIntegerSelector(alpha, 400, 250, { fillHover: '#444', fillClick: '#666' })

			// Draw omega selector
			drawImage('assets/character/omega.png', 600, 50, 200, 200)
			uiIntegerSelector(omega, 600, 250, { fillHover: '#444', fillClick: '#666' })

			// Draw start button
			if (uiRectButton(680, 470, 100, 100, { fillHover: '#F00', fillClick: '#800' })) {
				config = {
					name: 'Custom Night',
					unskippable: true,
					star: ((iota.value == 20 && omicron.value == 20 && alpha.value == 20 && omega.value == 20) ? 4 : 0),
					minutesPerMS: .001,
					powerConsumePerMinute: .18,
					iota: iota.value,
					omicron: omicron.value,
					alpha: alpha.value,
					omega: omega.value
				}
				gameState = 'gameStartAnimation'
				gameStartAnimationTime = 0
				stopAllAudio()
			}
			fillText('START!', 730, 520, { fontSize: 30 })

			// Draw buttons
			if (uiRectButton(20, 350, 200, 50, { fillHover: '#444', fillClick: '#666' })) {
				iota.value = 0
				omicron.value = 0
				alpha.value = 0
				omega.value = 0
			}
			fillText('0/0/0/0', 120, 377, { fontSize: 30 })
			if (uiRectButton(20, 410, 200, 50, { fillHover: '#444', fillClick: '#666' })) {
				iota.value = 5
				omicron.value = 5
				alpha.value = 5
				omega.value = 5
			}
			fillText('5/5/5/5', 120, 437, { fontSize: 30 })
			if (uiRectButton(20, 470, 200, 50, { fillHover: '#444', fillClick: '#666' })) {
				iota.value = 10
				omicron.value = 10
				alpha.value = 10
				omega.value = 10
			}
			fillText('10/10/10/10', 120, 497, { fontSize: 30 })
			if (uiRectButton(20, 530, 200, 50, { fillHover: '#444', fillClick: '#666' })) {
				iota.value = 20
				omicron.value = 20
				alpha.value = 20
				omega.value = 20
			}
			fillText('20/20/20/20', 120, 557, { fontSize: 30 })
			if (uiRectButton(240, 350, 200, 50, { fillHover: '#444', fillClick: '#666' })) {
				iota.value = 1
				omicron.value = 3
				alpha.value = 2
				omega.value = 2
			}
			fillText('Night 1', 340, 377, { fontSize: 30 })
			if (uiRectButton(240, 410, 200, 50, { fillHover: '#444', fillClick: '#666' })) {
				iota.value = 1
				omicron.value = 6
				alpha.value = 3
				omega.value = 3
			}
			fillText('Night 2', 340, 437, { fontSize: 30 })
			if (uiRectButton(240, 470, 200, 50, { fillHover: '#444', fillClick: '#666' })) {
				iota.value = 2
				omicron.value = 3
				alpha.value = 7
				omega.value = 4
			}
			fillText('Night 3', 340, 497, { fontSize: 30 })
			if (uiRectButton(460, 350, 200, 50, { fillHover: '#444', fillClick: '#666' })) {
				iota.value = 3
				omicron.value = 5
				alpha.value = 6
				omega.value = 8
			}
			fillText('Night 4', 560, 377, { fontSize: 30 })
			if (uiRectButton(460, 410, 200, 50, { fillHover: '#444', fillClick: '#666' })) {
				iota.value = 4
				omicron.value = 8
				alpha.value = 9
				omega.value = 7
			}
			fillText('Night 5', 560, 437, { fontSize: 30 })
			if (uiRectButton(460, 470, 200, 50, { fillHover: '#444', fillClick: '#666' })) {
				iota.value = 5
				omicron.value = 13
				alpha.value = 14
				omega.value = 8
			}
			fillText('Night 6', 560, 497, { fontSize: 30 })
			break
		case 'gameStartAnimation':
			// Draw background
			fillRect(0, 0, 800, 600)

			// Draw game description
			fillText(config.name, 400, 250, { fontSize: 72 })
			fillText('12:00 AM', 400, 350, { fontSize: 72 })

			// Handle timeout event
			gameStartAnimationTime += elapsed
			if (gameStartAnimationTime >= 2000) {
				gameState = 'game'
				state = createState()
			}
			break
		case 'game':
			renderState(config, state)
			updateState(config, state, elapsed)
			if (KEYBOARD_STATE['Equal'] && !config.unskippable)
				gameWin()
			//fillText('The game is on...', 400, 150, { fontSize: 50 })
			//fillText(JSON.stringify(config), 400, 200, { fontSize: 50 })
			break
		case 'lose':
			// Draw background
			fillRect(0, 0, 800, 600, { fill: '#222' })
			drawImage('assets/character/glitch/iota1.png', 100, 0, 600, 600)

			// Draw text
			fillText('GAME    OVER', 400, 180, { fontSize: 108 })

			// Draw retry button
			let retryButton = uiRectButton(200, 300, 400, 100, { fillHover: '#444', fillClick: '#666' })
			fillText('Retry night', 400, 350, { fontSize: 48 })

			// Draw menu button
			let menuButton = uiRectButton(200, 450, 400, 100, { fillHover: '#444', fillClick: '#666' })
			fillText('Menu', 400, 500, { fontSize: 48 })

			// Handle button events
			if (retryButton) {
				gameState = 'gameStartAnimation'
				gameStartAnimationTime = 0
				stopAllAudio()
			} else if (menuButton) {
				gameState = 'start'
				stopAllAudio()
				playAudio('assets/sound/music.ogg', true)
			}
			break
		case 'win':
			// Draw background
			fillRect(0, 0, 800, 600, { fill: '#222' })

			// Draw text
			gameWinAnimationTime += elapsed
			let gameWinAnimationPhase = (gameWinAnimationTime < 500) ? 0 : ((gameWinAnimationTime > 2500) ? 1 : ((gameWinAnimationTime - 500) * .0005))
			fillText('5:59', 400, 300 - 50 * gameWinAnimationPhase, { fontSize: 50, alignX: 'right' })
			fillText('6:00', 400, 350 - 50 * gameWinAnimationPhase, { fontSize: 50, alignX: 'right' })
			fillText(' AM', 400, 300, { fontSize: 50, alignX: 'left' })

			// Draw cover
			fillRect(0, 0, 800, 275, { fill: '#222' })
			fillRect(0, 325, 800, 275, { fill: '#222' })

			if (gameWinAnimationTime >= 10000) {
				switch (gameNextAction) {
					case 'nextlevel':
						config = GAME_CONFIG.levels[gameCurrentNight]
						gameState = 'gameStartAnimation'
						gameStartAnimationTime = 0
						break
					case 'ending':
						switch (config.name) {
							case 'Night 5':
								gameState = 'ending1'
								break
							case 'Night 6':
								gameState = 'credits1'
								playAudio('assets/sound/end.ogg', true)
								gameCreditAnimationTime = 0
								break
							case 'Custom Night':
								gameState = 'ending3'
								break
						}
						break
				}
			}
			break
		case 'ending1':
			// Draw background
			fillRect(0, 0, 800, 600, { fill: '#222' })

			// Draw text
			fillText('NIGHT 5 PASSED', 400, 180, { fontSize: 72 })

			// Draw retry button
			let retryButton2 = uiRectButton(200, 300, 400, 100, { fillHover: '#444', fillClick: '#666' })
			fillText('Retry night', 400, 350, { fontSize: 48 })

			// Draw menu button
			let menuButton2 = uiRectButton(200, 450, 400, 100, { fillHover: '#444', fillClick: '#666' })
			fillText('Menu', 400, 500, { fontSize: 48 })

			// Handle button events
			if (retryButton2) {
				gameState = 'gameStartAnimation'
				gameStartAnimationTime = 0
			} else if (menuButton2) {
				gameState = 'start'
				playAudio('assets/sound/music.ogg', true)
			}
			break
		case 'ending2':
			// Draw background
			fillRect(0, 0, 800, 600, { fill: '#222' })

			// Draw text
			fillText('NIGHT 6 PASSED', 400, 180, { fontSize: 72 })

			// Draw retry button
			let retryButton3 = uiRectButton(200, 300, 400, 100, { fillHover: '#444', fillClick: '#666' })
			fillText('Retry night', 400, 350, { fontSize: 48 })

			// Draw menu button
			let menuButton3 = uiRectButton(200, 450, 400, 100, { fillHover: '#444', fillClick: '#666' })
			fillText('Menu', 400, 500, { fontSize: 48 })

			// Handle button events
			if (retryButton3) {
				gameState = 'gameStartAnimation'
				gameStartAnimationTime = 0
				stopAllAudio()
			} else if (menuButton3) {
				gameState = 'start'
				stopAllAudio()
				playAudio('assets/sound/music.ogg', true)
			}
			break
		case 'ending3':
			// Draw background
			fillRect(0, 0, 800, 600, { fill: '#222' })

			// Draw text
			fillText('CUSTOM NIGHT PASSED', 400, 180, { fontSize: 72 })
			fillText(config.iota.toFixed(0) + '/' + config.omicron.toFixed(0) + '/' + config.alpha.toFixed(0) + '/' + config.omega.toFixed(0), 400, 250, { fontSize: 72 })

			// Draw retry button
			let retryButton4 = uiRectButton(200, 300, 400, 100, { fillHover: '#444', fillClick: '#666' })
			fillText('Retry night', 400, 350, { fontSize: 48 })

			// Draw menu button
			let menuButton4 = uiRectButton(200, 450, 400, 100, { fillHover: '#444', fillClick: '#666' })
			fillText('Menu', 400, 500, { fontSize: 48 })

			// Handle button events
			if (retryButton4) {
				gameState = 'gameStartAnimation'
				gameStartAnimationTime = 0
			} else if (menuButton4) {
				gameState = 'start'
				playAudio('assets/sound/music.ogg', true)
			}
			break
		case 'credits1':
			// Draw background
			fillRect(0, 0, 800, 600, { fill: '#515151' })

			// Draw images
			drawImage('assets/character/iota.png', 200, -100, 800, 800)
			drawImage('assets/character/glitch/iota1.png', 0, 100, 300, 300)
			drawImage('assets/character/glitch/iota2.png', 220, 100, 300, 300)
			drawImage('assets/character/glitch/iota3.png', 0, 320, 300, 300)
			drawImage('assets/character/glitch/iota0.png', 220, 320, 300, 300)

			// Draw text
			fillText('IOTA (ι)', 250, 80, { fontSize: 72 })

			// Handle animation time
			gameCreditAnimationTime += elapsed
			if (gameCreditAnimationTime >= 2000) {
				gameState = 'credits2'
			}
			break
		case 'credits2':
			// Draw background
			fillRect(0, 0, 800, 600, { fill: '#FFA2B9' })

			// Draw images
			drawImage('assets/character/omicron.png', -200, -100, 800, 800)
			drawImage('assets/character/glitch/omicron1.png', 280, 100, 300, 300)
			drawImage('assets/character/glitch/omicron2.png', 500, 100, 300, 300)
			drawImage('assets/character/glitch/omicron3.png', 280, 320, 300, 300)
			drawImage('assets/character/glitch/omicron0.png', 500, 320, 300, 300)

			// Draw text
			fillText('OMICRON (ο)', 550, 80, { fontSize: 72 })

			// Handle animation time
			gameCreditAnimationTime += elapsed
			if (gameCreditAnimationTime >= 4000) {
				gameState = 'credits3'
			}
			break
		case 'credits3':
			// Draw background
			fillRect(0, 0, 800, 600, { fill: '#29299D' })

			// Draw images
			drawImage('assets/character/alpha.png', 200, -100, 800, 800)
			drawImage('assets/character/glitch/alpha1.png', 0, 100, 300, 300)
			drawImage('assets/character/glitch/alpha2.png', 220, 100, 300, 300)
			drawImage('assets/character/glitch/alpha3.png', 0, 320, 300, 300)
			drawImage('assets/character/glitch/alpha0.png', 220, 320, 300, 300)

			// Draw text
			fillText('ALPHA (α)', 250, 80, { fontSize: 72 })

			// Handle animation time
			gameCreditAnimationTime += elapsed
			if (gameCreditAnimationTime >= 6000) {
				gameState = 'credits4'
			}
			break
		case 'credits4':
			// Draw background
			fillRect(0, 0, 800, 600, { fill: '#B8B8B8' })

			// Draw images
			drawImage('assets/character/omega.png', -200, -100, 800, 800)
			drawImage('assets/character/glitch/omega1.png', 280, 100, 300, 300)
			drawImage('assets/character/glitch/omega2.png', 500, 100, 300, 300)
			drawImage('assets/character/glitch/omega3.png', 280, 320, 300, 300)
			drawImage('assets/character/glitch/omega0.png', 500, 320, 300, 300)

			// Draw text
			fillText('OMEGA (ω)', 550, 80, { fontSize: 72 })

			// Handle animation time
			gameCreditAnimationTime += elapsed
			if (gameCreditAnimationTime >= 8000) {
				gameState = 'credits5'
			}
			break
		case 'credits5':
			// Draw background
			fillRect(0, 0, 800, 600, { fill: '#222' })

			// Draw text
			fillText('CREDITS', 400, 200, { fontSize: 72 })
			fillText('This game is powered by HTML5.', 400, 300, { fontSize: 36 })
			fillText('Images: created by YaYaYa', 400, 350, { fontSize: 36 })
			fillText('Sounds: downloaded from FNAF fandom wiki', 400, 400, { fontSize: 36 })
			fillText('Reference: MDN web docs', 400, 450, { fontSize: 36 })

			// Handle animation time
			gameCreditAnimationTime += elapsed
			if (gameCreditAnimationTime >= 12000) {
				gameState = 'ending2'
			}
			break
		default:
			// Draw background
			fillRect(0, 0, 800, 600)

			// Hint unknown game state error
			fillText('Unknown game state "' + gameState + '"', 400, 300, { fontSize: 60 })
	}
}

CURRENT_TIMESTAMP = undefined
function animationFrameCallback(timestamp) {
	if (CURRENT_TIMESTAMP !== undefined)
		update(timestamp - CURRENT_TIMESTAMP)
	CURRENT_TIMESTAMP = timestamp
	window.requestAnimationFrame(animationFrameCallback)
}
window.requestAnimationFrame(animationFrameCallback)